﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using MSWMDMLib;
using System.Runtime.InteropServices;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows.Controls.Primitives;
using System.Windows.Automation.Peers;
using System.ComponentModel;
using System.Threading.Tasks;
using Microsoft.WindowsAPICodePack.Shell;
using System.Diagnostics;
using FireZone.DataStructure;
using FireZone.NativeWMDMInteface;
using FireZone.OperationLogger;
using MS.WindowsAPICodePack.Internal;

namespace FireZone
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    /// 



    public partial class MainWindow : Window, IWMDMNotification
    {
        private ObservableCollection<MTPDeviceItem> mtpDeviceList = new ObservableCollection<MTPDeviceItem>();
        internal ObservableCollection<OperationLoggerItem> collectionForLog = new ObservableCollection<OperationLoggerItem>() 
        { 
            new OperationLoggerItem(){ DisplayName = "Begin:", DisplayMessage = DateTime.Now.ToString(), IsFailed = true, IsCompleted = true, IsCanceled= false,},
        };
        private MediaDevMgr mtpDevMgr;
        private uint dwCookie = 0;
        
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            mtpDevMgr = NativeMethod.MTPDeviceEnum();
            lstboxLog.ItemsSource = collectionForLog;
            IWMDeviceManager3 mtpDevMgrV3 = (IWMDeviceManager3)mtpDevMgr;
            int hr = mtpDevMgrV3.SetDeviceEnumPreference(WMDMDeviceEnumPreference.DO_NOT_VIRTUALIZE_STORAGES_AS_DEVICES);
            mtpDevMgrV3.Reinitialize();
            IConnectionPointContainer mtpCPC = (IConnectionPointContainer)mtpDevMgr;
            IConnectionPoint mtpCP;
            mtpCPC.FindConnectionPoint(new Guid("3F5E95C0-0F43-4ed4-93D2-C89A45D59B81"), out mtpCP);
            mtpCP.Advise((IWMDMNotification)this, out dwCookie);
            uint devCount = 0;
            mtpDevMgrV3.GetDeviceCount(out devCount);
            WMDMDeviceEnum wmdmDevEnum;
            mtpDevMgrV3.EnumDevices2(out wmdmDevEnum);
            while (true)
            {
                WMDMDevice mtpDev;
                uint uFetched = 0;
                wmdmDevEnum.Next(1, out mtpDev, out uFetched);
                if (uFetched == 0) break;
                mtpDeviceList.Add(new MTPDeviceItem() { DeviceItem = (IWMDMDevice3)mtpDev, });
            }                
            comboxDeviceList.ItemsSource = mtpDeviceList;
        }
        void IWMDMNotification.WMDMMessage(WMDMDeviceNotification dwMessageType, string pwszCanonicalName)        
        {
            switch(dwMessageType)
            {
                case WMDMDeviceNotification.WMDM_MSG_DEVICE_ARRIVAL:
                    {
                        Application.Current.Dispatcher.BeginInvoke(new Action(() => { 
                            IWMDeviceManager3 wmdmDevMgrV3 = (IWMDeviceManager3)mtpDevMgr;
                            WMDMDevice wmdmDev;
                            wmdmDevMgrV3.GetDeviceFromCanonicalName(pwszCanonicalName, out wmdmDev);
                            mtpDeviceList.Add(new MTPDeviceItem() { DeviceItem = (IWMDMDevice3)wmdmDev, });
                        }));
                    }
                    break;
                case WMDMDeviceNotification.WMDM_MSG_DEVICE_REMOVAL:
                    {
                        Application.Current.Dispatcher.BeginInvoke(new Action(() => { 
                            MTPDeviceItem mtpDevItem = mtpDeviceList.FirstOrDefault((item) => { return (item.deviceCanonicalName == pwszCanonicalName); });
                            mtpDevItem.Dispose();
                            mtpDeviceList.Remove(mtpDevItem);
                        }));
                    }
                    break;
                case WMDMDeviceNotification.WMDM_MSG_MEDIA_ARRIVAL:
                    {

                    }
                    break;
                case WMDMDeviceNotification.WMDM_MSG_MEDIA_REMOVAL:
                    {

                    }
                    break;
            }
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            IConnectionPointContainer mtpCPC = (IConnectionPointContainer)mtpDevMgr;
            IConnectionPoint mtpCP;
            mtpCPC.FindConnectionPoint(new Guid("3F5E95C0-0F43-4ed4-93D2-C89A45D59B81"), out mtpCP);
            mtpCP.Unadvise(dwCookie);
        }

        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {

        }

        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {

        }

        private void RadioCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
            e.Handled = true;
        }

        private void Radio_Checked(object sender, RoutedEventArgs e)
        {
            //MTPStorageItem StorageItem = comboxStorageList.SelectionBoxItem as MTPStorageItem;
            //if (StorageItem != null)
            //{
            //    MTPStorageItem stgChildItem = null;
            //    if (e.Source == btnVideo)
            //    {
            //        stgChildItem = StorageItem.ChildStorages.FirstOrDefault((stg) => { return (stg.StorageName == "Videos"); });
            //    }
            //    else if (e.Source == btnAudio)
            //    {
            //        stgChildItem = StorageItem.ChildStorages.FirstOrDefault((stg) => { return (stg.StorageName == "Audios"); });
            //    }
            //    else if (e.Source == btnPhoto)
            //    {
            //        stgChildItem = StorageItem.ChildStorages.FirstOrDefault((stg) => { return (stg.StorageName == "Photos"); });
            //    }
            //    else if (e.Source == btnSubtitle)
            //    {
            //        stgChildItem = StorageItem.ChildStorages.FirstOrDefault((stg) => { return (stg.StorageName == "Subtitles"); });
            //    }
            //    else if (e.Source == btnPowerPoint)
            //    {
            //        stgChildItem = StorageItem.ChildStorages.FirstOrDefault((stg) => { return (stg.StorageName == "PowerPoints"); });
            //    }
            //    else if (e.Source == btnFlash)
            //    {
            //        stgChildItem = StorageItem.ChildStorages.FirstOrDefault((stg) => { return (stg.StorageName == "Flashs"); });
            //    }
            //    else if (e.Source == btnPlaylist)
            //    {
            //        stgChildItem = StorageItem.ChildStorages.FirstOrDefault((stg) => { return (stg.StorageName == "Playlists"); });
            //    }
            //    if (stgChildItem != null)
            //    {
            //        listViewStorage.ItemsSource = stgChildItem.ChildStorages;
            //    }
            //    else
            //    {
            //        listViewStorage.ItemsSource = null;
            //    }
            //}
        }

        private void Radio_Unchecked(object sender, RoutedEventArgs e)
        {

        }



        private void RadioCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {

        }
        private void listViewStorage_PasteFromIDataObject(ListView listViewStorage,  IDataObject dataobj)
        {
            string[] filenames = (string[])dataobj.GetData(DataFormats.FileDrop);
            if (filenames != null)
            {
                ////////////!!!!!This is root storage item, select corresponding folder by file extension
                (comboxStorageList.SelectedItem as MTPStorageItem).MTPInsertFilesToPredefinedStorageAsync((comboxStorageList.SelectedItem as MTPStorageItem), (comboxDeviceList.SelectedItem as MTPDeviceItem).CancellationToken, (comboxDeviceList.SelectedItem as MTPDeviceItem).OperationTaskScheduler, filenames);
            }
        }
        private void listViewStorage_Drop(object sender, DragEventArgs e)
        {
            listViewStorage_PasteFromIDataObject((ListView)sender, e.Data);
        }

        private void listViewStorage_DragEnter(object sender, DragEventArgs e)
        {
            ListView listViewStorage = e.Source as ListView; 
            e.Handled = true;
            e.Effects = ((e.Data.GetData(DataFormats.FileDrop) != null) && (listViewStorage.DataContext != null)) ? e.Effects : DragDropEffects.None;
        }

        private void listViewStorage_DragOver(object sender, DragEventArgs e)
        {
            ListView listViewStorage = e.Source as ListView;
            e.Handled = true;
            e.Effects = ((e.Data.GetData(DataFormats.FileDrop) != null) && (listViewStorage.DataContext != null)) ? e.Effects : DragDropEffects.None;
        }


        private void PasteStorageCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            ListView listViewStorage = e.Source as ListView;
            if ((listViewStorage != null) && (listViewStorage.DataContext != null))
            {
                e.CanExecute = Clipboard.ContainsFileDropList();
                e.Handled = true;
            }
        }


        private void PasteStorageCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            ListView listViewStorage = e.Source as ListView;
            if (listViewStorage != null)
            {
                listViewStorage_PasteFromIDataObject(listViewStorage, Clipboard.GetDataObject());
            }
        }

        private void CopyStorageCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            ListView listViewStorage = e.Source as ListView;
            if (listViewStorage != null)
            {
                e.CanExecute = (listViewStorage.SelectedItems.Count > 0);
                e.Handled = true;
            }
        }

        private void CopyStorageCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {

        }

        private void CutStorageCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            ListView listViewStorage = e.Source as ListView;
            if (listViewStorage != null)
            {
                e.CanExecute = (listViewStorage.SelectedItems.Count > 0);
                e.Handled = true;    
            }
        }

        private void CutStorageCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {

        }

        private void DeleteStorageCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            ListView listViewStorage = e.Source as ListView;
            if(listViewStorage != null)
            {
                e.CanExecute = (listViewStorage.SelectedItem != null);
                e.Handled = true;
            }
        }

        private void DeleteStorageCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            ListView listViewStorage = e.Source as ListView;
            if (listViewStorage != null)
            {
                (listViewStorage.DataContext as MTPStorageItem).MTPDeleteFilesAsync((comboxStorageList.SelectedItem as MTPStorageItem), (comboxDeviceList.SelectedItem as MTPDeviceItem).CancellationToken, (comboxDeviceList.SelectedItem as MTPDeviceItem).OperationTaskScheduler, listViewStorage.SelectedItems.Cast<MTPStorageItem>().ToList());                
            }
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MTPDeviceItem.RenewCancellationTokenSource(comboxDeviceList.SelectedItem as MTPDeviceItem);
        }

        private void SetAsDefaultPlaylistCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            ListView listViewStorage = e.Source as ListView;
            if (listViewStorage != null)
            {
                e.CanExecute = (listViewStorage.SelectedItems.Count == 1);
                e.Handled = true;
            }    
        }

        private void SetAsDefaultPlaylistCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            (comboxStorageList.SelectedItem as MTPStorageItem).MTPSetAsDefaultPlaylist(((ListView)e.Source).SelectedItem as MTPStorageItem);
        }

        private void AddToDefaultPlaylistCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            ListView listViewStorage = e.Source as ListView;
            if (listViewStorage != null)
            {
                e.CanExecute = (listViewStorage.SelectedItem != null);
                e.Handled = true;
            }               
        }

        private void AddToDefaultPlaylistCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            (comboxStorageList.SelectedItem as MTPStorageItem).MTPAddItemsToDefaultPlaylist(((ListView)e.Source).SelectedItems.OfType<MTPStorageItem>());

        }

        private void CreateAsPlaylistCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            ListView listViewStorage = e.Source as ListView;
            if (listViewStorage != null)
            {
                e.CanExecute = (listViewStorage.SelectedItem != null);
                e.Handled = true;
            }            
        }

        private void CreateAsPlaylistCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            (comboxStorageList.SelectedItem as MTPStorageItem).MTPCreateAsPlaylist(((ListView)e.Source).SelectedItems.OfType<MTPStorageItem>());
        }

        private void RemoveFromPlaylistCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            ListView listViewStorage = e.Source as ListView;
            if (listViewStorage != null)
            {
                e.CanExecute = (listViewStorage.SelectedItem != null);
                e.Handled = true;
            }  
        }

        private void RemoveFromPlaylistCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            (comboxStorageList.SelectedItem as MTPStorageItem).MTPRemoveItemsFromPlaylist(((ListView)e.Source).SelectedItems.OfType<MTPStorageItem>());
        }

        private void DeviceSupportProperties_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            using (PropVariant propVar = new PropVariant())
            {
                IWMDMDevice3 wmdmDevice = (comboxDeviceList.SelectedItem as MTPDeviceItem).DeviceItem;
                wmdmDevice.GetProperty(WMDM_DATATYPE_DESC.g_wszWMDMSupportedDeviceProperties, propVar);
                string[] supportPropList = (string[])propVar.Value;
                string tooltipInnerText = "";
                ObservableCollection<Tuple<string, string>> tooltipTextCollection = new ObservableCollection<Tuple<string, string>>();
                foreach (var item in supportPropList.Distinct())
                {
                    using (PropVariant propVarItem = new PropVariant())
                    {
                        wmdmDevice.GetProperty(item, propVarItem);
                        switch (item)
                        {
                            case "WMDM/DeviceProtocol":
                                {
                                    tooltipTextCollection.Add(new Tuple<string, string>(item, typeof(WMDM_DEVICE_PROTOCOL).FindClassStaticFieldNameByValue(propVarItem.Value)));
                                }
                                break;
                            case "WMDM/FormatsSupported":
                                {
                                    tooltipTextCollection.Add(new Tuple<string, string>(item, string.Join("\r\n", ((uint[])propVarItem.Value).Select((i) => { return typeof(WMDM_FORMATCODE).FindClassStaticFieldNameByValue(i); }))));                                                                    
                                }
                                break;
                            case "WMDM/DeviceServiceProviderVendor":
                                {
                                    tooltipTextCollection.Add(new Tuple<string, string>(item, typeof(WMDM_SERVICE_PROVIDER_VENDOR).FindClassStaticFieldNameByValue(propVarItem.Value)));
                                }
                                break;
                            default:
                                {
                                    tooltipTextCollection.Add(new Tuple<string, string>(item, propVarItem.Value.ToString()));
                                }
                                break;
                        }
                    }
                }                
                //(comboxDeviceList.SelectedItem as MTPDeviceItem).ToolTipText = tooltipInnerText;  
                (this.FindResource("DeviceSupportPropertiesToolTip") as ToolTip).DataContext = tooltipTextCollection;
                (this.FindResource("DeviceSupportPropertiesToolTip") as ToolTip).IsOpen = true;
            }
        }

        void tt_Closed(object sender, RoutedEventArgs e)
        {
            (sender as ToolTip).Closed -= new RoutedEventHandler(tt_Closed);
            TextBlock tb = (sender as ToolTip).Content as TextBlock;
            (comboxDeviceList.SelectedItem as MTPDeviceItem).ToolTipText = "";
        }

        private void DeviceSupportProperties_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = (comboxDeviceList.SelectedItem != null);
            e.Handled = true;
        }
        void SetGlowVisibility(ProgressBar progressBar, Visibility visibility)
        {
            var glow = progressBar.Template.FindName("PART_GlowRect", progressBar) as FrameworkElement;
            if (glow != null) glow.Visibility = visibility;
        }

        private void RefreshCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
            e.Handled = true;
        }

        private void RefreshCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {

        }
    }
}
